﻿using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using GN.Pay.Utils;
using System.Text;
using GN.Pay.TradeChannel.Configure;

namespace GN.Pay.TradeChannel
{
    /// <summary>
    /// 交易通道抽象
    /// </summary>
    [Serializable]
    public abstract class ATradeChannel<TNotify> : ITradeChannel<TNotify> where TNotify : class
    {
        /// <summary>
        /// 实例化 ATradeChannel 类新实例
        /// </summary>
        /// <param name="channelConfigure">通道配置</param>
        protected ATradeChannel()
        {
        }

        /// <summary>
        /// 获取通道类型
        /// </summary>
        public abstract ChannelType ChannelType { get; }

        /// <summary>
        /// 读取配置产生的事件
        /// </summary>
       // public event EventHandler ReadConfigure;

        /// <summary>
        /// 获取通道配置
        /// </summary>
        public abstract ITradeChannelConfigure ChannelConfigure { get; }

        /// <summary>
        /// 获取通道Id
        /// </summary>
        public abstract string ChannelId { get; }

        /// <summary>
        /// 获取通道名称
        /// </summary>
        public abstract string ChannelName { get; }

        /// <summary>
        /// 获取通道提供者
        /// </summary>
        public abstract string ChannelProvider { get; }

        /// <summary>
        /// 获取付款是否每次都是新请求
        /// </summary>
        public virtual bool IsPayNewRequest
        {
            get { return true; }
        }

        /// <summary>
        /// 
        /// </summary>
        public abstract Type TradeChannelConfigureInfoType { get; }
       

        public abstract void OrderRefundNotify(INotifyService sercice, TNotify message);

        void ITradeChannel.OrderRefundNotify(INotifyService sercice, object message)
        {
            this.OrderRefundNotify(sercice, message as TNotify);
        }

        async Task ITradeChannel.OrderRefundNotifyAsync(INotifyService sercice, object message)
        {
            await this.OrderRefundNotifyAsync(sercice, message as TNotify);
        }

        public async Task OrderRefundNotifyAsync(INotifyService sercice, TNotify message)
        {
            await Task.Run(() =>
            {
                this.OrderRefundNotify(sercice, message);
            });
        }

        public abstract void OrderPayNotify(INotifyService sercice, TNotify message);

        void ITradeChannel.OrderPayNotify(INotifyService sercice, object message)
        {
            this.OrderPayNotify(sercice, message as TNotify);
        }

        async Task ITradeChannel.OrderPayNotifyAsync(INotifyService sercice, object message)
        {
            await this.OrderPayNotifyAsync(sercice, message as TNotify);
        }

        public async Task OrderPayNotifyAsync(INotifyService sercice, TNotify message)
        {
            await Task.Run(() =>
            {
                this.OrderPayNotify(sercice, message);
            });
        }

        public abstract ITradeOrderQueryResult OrderSingleQuery(DateTime queryDate, string orderNo, string tradeNo);

        public async Task<ITradeOrderQueryResult> OrderSingleQueryAsync(DateTime queryDate, string orderNo, string tradeNo)
        {
            return await Task.Run<ITradeOrderQueryResult>(() =>
            {
                return this.OrderSingleQuery(queryDate, orderNo, tradeNo);
            });
        }

        /// <summary>
        /// 订单单笔查询是否可靠
        /// </summary>
        public virtual bool OrderSingleQueryIsReliable
        {
            get
            {
                return true;
            }
        }

        public abstract ITradePayApplyResult PayApply(IOrderPayApply order);

        public async Task<ITradePayApplyResult> PayApplyAsync(IOrderPayApply order)
        {
            return await Task.Run<ITradePayApplyResult>(() =>
            {
                return this.PayApply(order);
            });
        }

        public abstract ITradeRefundApplyResult RefundApply(IRefundApplyInfo apply);

        public async Task<ITradeRefundApplyResult> RefundApplyAsync(IRefundApplyInfo apply)
        {
            return await Task.Run<ITradeRefundApplyResult>(() =>
            {
                return this.RefundApply(apply);
            });
        }

        /// <summary>
        /// 获取百分制金额
        /// </summary>
        /// <param name="value">值</param>
        /// <returns></returns>
        public long GetPercentMoney(decimal value)
        {
            return Convert.ToInt64(Math.Round(value, 2)) * 100;
        }

        /// <summary>
        /// 获取百分制实际金额
        /// </summary>
        /// <param name="value">值</param>
        /// <returns></returns>
        public decimal GetPercentActualMoney(long value)
        {
            return Math.Round(new decimal(value / 100), 2);
        }

        /// <summary>
        /// 支付通知响应
        /// </summary>
        /// <param name="isSuccess"></param>
        /// <returns></returns>
        public abstract string PayNotifyResponse(bool isSuccess);

        /// <summary>
        /// 退款通知响应
        /// </summary>
        /// <param name="isSuccess"></param>
        /// <returns></returns>
        public abstract string RefundNotifyResponse(bool isSuccess);
    }
}
